package cu.ds.logicalsync.fytasrealm;

/*
 * DesktopApplication1.java
 */

import java.util.ArrayList;

import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

import cu.ds.logicalsync.fytasrealm.communication.CommunicationException;
import cu.ds.logicalsync.fytasrealm.communication.Network;
import cu.ds.logicalsync.fytasrealm.communication.event.PeerStatusEvent;
import cu.ds.logicalsync.fytasrealm.communication.event.PeerStatusListener;
import cu.ds.logicalsync.fytasrealm.communication.model.PeerInfo;
import cu.ds.logicalsync.fytasrealm.model.Map;
import cu.ds.logicalsync.fytasrealm.model.PositionWorld;
import cu.ds.logicalsync.fytasrealm.model.Warrior;
import cu.ds.logicalsync.fytasrealm.model.World;
import cu.ds.logicalsync.fytasrealm.ui.MainWindow;
import cu.ds.logicalsync.fytasrealm.util.Tools;

/**
 * The main class of the application.
 */
public class FytasRealmDesktop extends SingleFrameApplication {
	private MainWindow view;
	private Network network;
	private PeerInfo myPeerInfo;
	private World myWorld;
	private Warrior myWarrior;

    /**
	 * @return the net
	 */
	public Network getNetWork() {
		return network;
	}

	/**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
    	this.view = new MainWindow(this);
        
        initialize();
        
        show(this.view);
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of DesktopApplication1
     */
    public static FytasRealmDesktop getApplication() {
        return Application.getInstance(FytasRealmDesktop.class);
    }

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(FytasRealmDesktop.class, args);
    }
    
    /************* Non generated code *************/
    
    /**
     * Initialize Clients communication
	 */
	private void initialize() {
		// Get client credential for further communication reference
		String clientCredential = (String) this.view.openLoginDialog();
		
		// TODO: Use Log4J
		System.out.println("clientCredential = " + clientCredential);
		this.view.setClientName(clientCredential);
		
		// TODO: Using ServiceFacade
		/*this.netService = new NetworkService(clientCredential);
		this.netService.addObserver(this.view.getPeersPanel());
		this.netService.start();*/
		
		/*this.discoveryService = new DiscoveryServiceProvider(clientCredential);
		this.discoveryService.addObserver(this.view.getPeersPanel());
		this.discoveryService.start();*/
		
		// Test with Mock Services
		/*this.discoveryServiceMock = new DiscoveryServiceMock(clientCredential);
		this.discoveryServiceMock.addObserver(this.view.getPeersPanel());
		this.discoveryServiceMock.start();*/
		
		//TODO: Call Game Loop here!
		//String newName = "client1";
		//World world = new World(clientCredential);
		
		
		
		// Initial Network and Services 
		// Clean slate
		Tools.deleteConfigurationInDefaultHome();
		
		network = new Network(clientCredential);
		network.start();
		
		// Check name
		boolean isNameExisted = network.getPeerStatusService().isNameExisted(clientCredential);
		if(isNameExisted) {
			Tools.popErrorMsg("Application Error", "This name is already in used by other client");
			this.exit();
		}
		
		myPeerInfo = network.getPeerStatusService().login(clientCredential);
		try {
			myWorld = network.getMapStatusService().createNewWorld();
		} catch (CommunicationException e) {
			e.printStackTrace();
			Tools.popErrorMsg("Application Error", "Cannot create my World");
		}
		// register myWorld with Network
		network.setMyWorld(myWorld);
		
		Map map = new Map(); // TODO: get updated map from event
		network.setCurrentMap(map); // register myMap with Network
		
		myWarrior = new Warrior(clientCredential);
		myWarrior.setPeerInfo(myPeerInfo);
		myWarrior.setMyWorld(myWorld);
		myWarrior.setMyCurrentWorld(myWorld);
		System.out.println("New warrior: "+ clientCredential +" is created.");
		System.out.println("New world: "+ clientCredential +" is created.");
		// register myWarrior with Network
		network.setMyWarrior(myWarrior);
		
		
		view.setWorld(myWorld);
		view.setMap(map);
		view.setWarrior(myWarrior);
		
		view.drawItAll();
	}
	
	
	/***** App logic ******/
	
	/**
	 * Request change world 
	 * @param row
	 * @param col
	 */
	public void changeWorld(int row, int col) {
		
	}
	
	/**
	 * Move Warrior
	 * @param direction
	 */
	public void move(MoveDirection direction,Warrior warrior) {
		PositionWorld pw = warrior.getMyPositionInWorld();
		int currentRow = pw.getRowPosition();
		int currentCol = pw.getColPosition();
		int newRow = currentRow;
		int newCol = currentCol;
		
		//pw.setPositionOccupy(false); //free current position
		//pw.setWarriorNameInWorld(null);
		
		// free current position
		PositionWorld oldPosition = new PositionWorld(currentRow, currentCol);
		oldPosition.setPositionOccupy(false);
		oldPosition.setWarriorNameInWorld(null);
		
		myWorld.setWorldRoom(currentRow, currentCol, oldPosition);
				
		if(direction.equals(MoveDirection.Left)) {
			if (currentCol != 0) {
				newCol--;
				System.out.println(warrior.getWarriorName() + " moves left.");
			}
		}
		else if (direction.equals(MoveDirection.Right)) {
			if (currentCol != 7) {
				newCol++;
				System.out.println(warrior.getWarriorName() + " moves right.");
			}
		}
		else if (direction.equals(MoveDirection.Up)) {
			if (currentRow != 0) {
				newRow--;
				System.out.println(warrior.getWarriorName() + " moves up.");
			}
		}
		else if (direction.equals(MoveDirection.Down)) {
			if (currentRow != 7) {
				newRow++;
				System.out.println(warrior.getWarriorName() + " moves down.");
			}
		}
		pw.setRowPosition(newRow);
		pw.setColPosition(newCol);
		pw.setPositionOccupy(true);
		pw.setWarriorNameInWorld(warrior.getWarriorName());
		
		
		ArrayList<PositionWorld> warriorPlaces = myWorld.findOccupiedPositions();
		
		myWorld.setWorldRoom(newRow, newCol, pw);
		view.setWorld(myWorld);
		
	}
}
